home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / ixemul-complete / ixemul / library / socket.c < prev    next >
C/C++ Source or Header  |  1996-08-13  |  10KB  |  519 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1996 by Jeff Shepherd
  5.  *  Portions Copyright (C) 1996 by Hans Verkuil
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #define _KERNEL
  23. #include "ixemul.h"
  24. #include "kprintf.h"
  25.  
  26. #include <sys/socket.h>
  27. #include <sys/socketvar.h>
  28. #include <sys/unix_socket.h>
  29. #include <sys/ioctl.h>
  30. #include <net/if.h>
  31. #include <net/route.h>
  32. #include <netinet/in.h>
  33. #include <machine/param.h>
  34. #include <string.h>
  35.  
  36. static struct file *getsock (int fdes);
  37. static int soo_read   (struct file *fp, char *buf, int len);
  38. static int soo_write  (struct file *fp, char *buf, int len);
  39. static int soo_ioctl  (struct file *fp, int cmd, int inout, int arglen, caddr_t data);
  40. static int soo_select (struct file *fp, int select_cmd, int io_mode, fd_set *ignored, u_long *also_ignored);
  41. static int soo_close  (struct file *fp);
  42. void _set_socket_params(struct file *fp, int type);
  43.  
  44. static void socket_cleanup(int ostat)
  45. {
  46.   if (CURSIG (&u))
  47.     SetSignal (0, SIGBREAKF_CTRL_C);
  48.  
  49.   u.p_stat = ostat;
  50.  
  51.   if (errno == EINTR)
  52.     setrun (FindTask (0));
  53.  
  54.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  55. }
  56.  
  57. static void socket_cleanup_epipe(int ostat)
  58. {
  59.   if (CURSIG (&u))
  60.     SetSignal (0, SIGBREAKF_CTRL_C);
  61.  
  62.   u.p_stat = ostat;
  63.  
  64.   /* the library doesn't send this to us of course ;-) */
  65.   if (errno == EPIPE)
  66.     _psignal (FindTask (0), SIGPIPE);
  67.  
  68.   if (errno == EINTR)
  69.     setrun (FindTask (0));
  70.  
  71.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  72. }
  73.  
  74. int
  75. socket (int domain, int type, int protocol)
  76. {
  77.   struct file *fp;
  78.   int fd, err, ostat, omask;
  79.  
  80.   if (!u.u_ixnetbase)
  81.     {
  82.       errno = ENOSYS;
  83.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  84.       return -1;
  85.     }
  86.  
  87.   ostat = u.p_stat;
  88.   u.p_stat = SWAIT;
  89.   omask = syscall (SYS_sigsetmask, ~0);
  90.  
  91.   do
  92.     {
  93.       if ((err = falloc (&fp, &fd)))
  94.         break;
  95.  
  96.       fp->f_so = netcall(NET__socket, domain, type, protocol);
  97.       err = (fp->f_so == -1) ? errno : 0;
  98.  
  99.       if (err)
  100.         {
  101.       /* free the allocated fd */
  102.           u.u_ofile[fd] = 0;
  103.           fp->f_count = 0;
  104.           break;
  105.         }
  106.  
  107.       _set_socket_params(fp, domain);
  108.     }
  109.   while (0);
  110.  
  111.   syscall (SYS_sigsetmask, omask);
  112.   errno = err;
  113.   socket_cleanup(ostat);
  114.   return err ? -1 : fd;
  115. }
  116.  
  117.  
  118. int
  119. bind (int s, const struct sockaddr *name, int namelen)
  120. {
  121.   struct file *fp = getsock (s);
  122.   int ostat, error;
  123.  
  124.   if (! fp)
  125.     return -1;
  126.  
  127.   ostat = u.p_stat;
  128.   u.p_stat = SWAIT;
  129.   error = netcall(NET__bind, fp, name, namelen);
  130.   socket_cleanup(ostat);
  131.   return error;
  132. }
  133.  
  134. int
  135. listen (int s, int backlog)
  136. {
  137.   struct file *fp = getsock (s);
  138.   int ostat, error;
  139.  
  140.   if (! fp)
  141.     return -1;
  142.  
  143.   ostat = u.p_stat;
  144.   u.p_stat = SWAIT;
  145.  
  146.   error = netcall(NET__listen, fp, backlog);
  147.   socket_cleanup(ostat);
  148.   return error;
  149. }
  150.  
  151. int
  152. accept (int s, struct sockaddr *name, int *namelen) 
  153. {
  154.   struct file *fp = getsock (s), *fp2;
  155.   int err, fd2, ostat;
  156.  
  157.   if (! fp)
  158.     return -1;
  159.  
  160.   ostat = u.p_stat;
  161.   u.p_stat = SWAIT;
  162.  
  163.   do
  164.     {
  165.       /* first try to get a new descriptor. If that fails, don't even
  166.          bother to call the library */
  167.       if ((err = falloc (&fp2, &fd2)))
  168.         break;
  169.  
  170.       fp2->f_so = netcall(NET__accept, fp, name, namelen);
  171.       err = (fp2->f_so == -1) ? errno : 0;
  172.       if (err)
  173.         {
  174.           /* the second file */
  175.           u.u_ofile[fd2] = 0;
  176.           fp2->f_count = 0;
  177.           break;
  178.         }
  179.       _set_socket_params(fp2, (fp->f_type == DTYPE_SOCKET) ? AF_INET : AF_UNIX);
  180.     }
  181.   while (0);
  182.  
  183.   errno = err;
  184.   socket_cleanup(ostat);
  185.   return err ? -1 : fd2;
  186. }
  187.  
  188.  
  189. int
  190. connect (int s, const struct sockaddr *name, int namelen)
  191. {
  192.   struct file *fp = getsock (s);
  193.   int ostat, error;
  194.  
  195.   if (! fp)
  196.     return -1;
  197.  
  198.   ostat = u.p_stat;
  199.   u.p_stat = SWAIT;
  200.  
  201.   error = netcall(NET__connect, fp, name, namelen);
  202.   socket_cleanup(ostat);
  203.   return error;
  204. }
  205.  
  206. int
  207. socketpair (int domain, int type, int protocol, int sv[2])
  208. {
  209.   errno = EPFNOSUPPORT;
  210.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  211.   return -1;
  212. }
  213.  
  214. int
  215. sendto (int s, const void *buf, int len, int flags, const struct sockaddr *to, int tolen)
  216. {
  217.   struct file *fp = getsock (s);
  218.   int ostat;
  219.   int rc;
  220.  
  221.   if (! fp || fp->f_type == DTYPE_USOCKET)
  222.     return -1;
  223.  
  224.   ostat = u.p_stat;
  225.   u.p_stat = SWAIT;
  226.  
  227.   rc = netcall(NET__sendto, fp, buf, len, flags, to, tolen);
  228.   socket_cleanup_epipe(ostat);
  229.   return rc;
  230. }
  231.  
  232.  
  233. int
  234. send (int s, const void *buf, int len, int flags)
  235. {
  236.   struct file *fp = getsock (s);
  237.   int ostat;
  238.   int rc;
  239.  
  240.   if (! fp)
  241.     return -1;
  242.  
  243.   ostat = u.p_stat;
  244.   u.p_stat = SWAIT;
  245.  
  246.   rc = netcall(NET__send, fp, buf, len, flags);
  247.   socket_cleanup_epipe(ostat);
  248.   return rc;
  249. }
  250.  
  251.  
  252. int
  253. sendmsg (int s, const struct msghdr *msg, int flags)
  254. {
  255.   struct file *fp = getsock (s);
  256.   int ostat, rc;
  257.  
  258.   if (!fp || fp->f_type == DTYPE_USOCKET)
  259.     return -1;
  260.  
  261.   ostat = u.p_stat;
  262.   u.p_stat = SWAIT;
  263.  
  264.   rc = netcall(NET__sendmsg, fp, msg, flags);
  265.   socket_cleanup_epipe(ostat);
  266.   return rc;
  267. }
  268.  
  269.  
  270. int
  271. recvfrom (int s, void *buf, int len, int flags, struct sockaddr *from, int *fromlen)
  272. {
  273.   struct file *fp = getsock (s);
  274.   int ostat, rc;
  275.  
  276.   if (!fp || fp->f_type == DTYPE_USOCKET)
  277.     return -1;
  278.  
  279.   ostat = u.p_stat;
  280.   u.p_stat = SWAIT;
  281.  
  282.   rc = netcall(NET__recvfrom, fp, buf, len, flags, from, fromlen);
  283.   socket_cleanup(ostat);
  284.   return rc;
  285. }
  286.  
  287.  
  288. int
  289. recv (int s, void *buf, int len, int flags)
  290. {
  291.   struct file *fp = getsock (s);
  292.   int ostat, rc;
  293.  
  294.   if (! fp)
  295.     return -1;
  296.  
  297.   ostat = u.p_stat;
  298.   u.p_stat = SWAIT;
  299.  
  300.   rc = netcall(NET__recv, fp, buf, len, flags);
  301.   socket_cleanup(ostat);
  302.   return rc;
  303. }
  304.  
  305.  
  306. int
  307. recvmsg (int s, struct msghdr *msg, int flags)
  308. {
  309.   struct file *fp = getsock (s);
  310.   int ostat, rc;
  311.  
  312.   if (!fp || fp->f_type == DTYPE_USOCKET)
  313.     return -1;
  314.  
  315.   ostat = u.p_stat;
  316.   u.p_stat = SWAIT;
  317.  
  318.   rc = netcall(NET__recvmsg, fp, msg, flags);
  319.   socket_cleanup(ostat);
  320.   return rc;
  321. }
  322.  
  323.  
  324. int
  325. shutdown (int s, int how) 
  326. {
  327.   struct file *fp = getsock (s);
  328.   int ostat, err;
  329.  
  330.   if (! fp)
  331.     return -1;
  332.  
  333.   ostat = u.p_stat;
  334.   u.p_stat = SWAIT;
  335.  
  336.   err = netcall(NET__shutdown, fp, how);
  337.   socket_cleanup(ostat);
  338.   return err;
  339. }
  340.  
  341.  
  342. int
  343. setsockopt (int s, int level, int name, const void *val, int valsize)
  344. {
  345.   struct file *fp = getsock (s);
  346.   int ostat, err;
  347.  
  348.   if (! fp)
  349.     return -1;
  350.  
  351.   ostat = u.p_stat;
  352.   u.p_stat = SWAIT;
  353.  
  354.   err = netcall(NET__setsockopt, fp, level, name, val, valsize);
  355.   socket_cleanup(ostat);
  356.   return err;
  357. }
  358.  
  359.  
  360. int
  361. getsockopt (int s, int level, int name, void *val, int *valsize)
  362. {
  363.   struct file *fp = getsock (s);
  364.   int ostat, err;
  365.  
  366.   if (! fp)
  367.     return -1;
  368.  
  369.   ostat = u.p_stat;
  370.   u.p_stat = SWAIT;
  371.  
  372.   err = netcall(NET__getsockopt, fp, level, name, val, valsize);
  373.   socket_cleanup(ostat);
  374.   return err;
  375. }
  376.  
  377.  
  378. /*
  379.  * Get socket name.
  380.  */
  381. int
  382. getsockname (int fdes, struct sockaddr *asa, int *alen)
  383. {
  384.   struct file *fp = getsock (fdes);
  385.   int ostat, err;
  386.  
  387.   if (! fp)
  388.     return -1;
  389.  
  390.   ostat = u.p_stat;
  391.   u.p_stat = SWAIT;
  392.  
  393.   err = netcall(NET__getsockname, fp, asa, alen);
  394.   socket_cleanup(ostat);
  395.   return err;
  396. }
  397.  
  398. /*
  399.  * Get name of peer for connected socket.
  400.  */
  401. int
  402. getpeername (int fdes, struct sockaddr *asa, int *alen)
  403. {
  404.   struct file *fp = getsock (fdes);
  405.   int ostat, err;
  406.  
  407.   if (! fp)
  408.     return -1;
  409.  
  410.   ostat = u.p_stat;
  411.   u.p_stat = SWAIT;
  412.  
  413.   err = netcall(NET__getpeername, fp, asa, alen);
  414.   socket_cleanup(ostat);
  415.   return err;
  416. }
  417.  
  418. static struct file *
  419. getsock (int fdes)
  420. {
  421.   struct file *fp;
  422.  
  423.   if ((unsigned) fdes >= NOFILE)
  424.     {
  425.       errno = EBADF;
  426.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  427.       return 0;
  428.     }
  429.  
  430.   fp = u.u_ofile[fdes];
  431.  
  432.   if (fp == NULL)
  433.     {
  434.       errno = EBADF;
  435.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  436.       return 0;
  437.     }
  438.  
  439.   if (fp->f_type != DTYPE_SOCKET && fp->f_type != DTYPE_USOCKET)
  440.     {
  441.       errno = ENOTSOCK;
  442.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  443.       return 0;
  444.     }
  445.  
  446.   if (fp->f_type == DTYPE_SOCKET && !u.u_ixnetbase)
  447.     {
  448.       errno = EPIPE; /* ????? */
  449.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  450.       return 0;
  451.     }
  452.  
  453.   return (fp);
  454. }
  455.  
  456. static int
  457. soo_read (struct file *fp, char *buf, int len)
  458. {
  459.   return netcall(NET__tcp_read, fp, buf, len);
  460. }
  461.  
  462. static int
  463. soo_write (struct file *fp, char *buf, int len)
  464. {
  465.   return netcall(NET__tcp_write, fp, buf, len);
  466. }
  467.  
  468. static int
  469. soo_ioctl (struct file *fp, int cmd, int inout, int arglen, caddr_t data)
  470. {
  471.   return netcall(NET__tcp_ioctl, fp, cmd, inout, arglen, data);
  472. }
  473.  
  474. /* ix_lock_base() is very fussy - so put most of the close() code here */
  475. static int
  476. soo_close (struct file *fp)
  477. {
  478.   int err;
  479.  
  480.   ix_lock_base ();
  481.   err = --fp->f_count;
  482.   ix_unlock_base ();
  483.  
  484.   if (err)
  485.     return 0;
  486.  
  487.   err = netcall(NET__tcp_close, fp);
  488.  
  489.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  490.   return err;
  491. }
  492.  
  493. static int
  494. soo_select(struct file *fp, int select_cmd, int io_mode,
  495.        fd_set *ignored, u_long *also_ignored)
  496. {
  497.   return netcall(NET__tcp_select, fp, select_cmd, io_mode, ignored, also_ignored);
  498. }
  499.  
  500. /* needed to set of the function pointers */
  501. void _set_socket_params(struct file *fp, int type)
  502. {
  503.   fp->f_stb.st_mode = 0666 | S_IFSOCK; /* not always, but.. */
  504.   fp->f_stb.st_size = 128;    /* sizeof mbuf. */
  505.   fp->f_stb.st_blksize = 128;
  506.   fp->f_type = type;
  507.   fp->f_flags = FREAD|FWRITE;
  508.   fp->f_type = ( (type == AF_INET) ? DTYPE_SOCKET : DTYPE_USOCKET);
  509.  
  510.   if (fp->f_type == DTYPE_SOCKET)
  511.     {
  512.       fp->f_read   = soo_read;
  513.       fp->f_write  = soo_write;
  514.       fp->f_ioctl  = soo_ioctl;
  515.       fp->f_close  = soo_close;
  516.       fp->f_select = soo_select;
  517.     }
  518. }
  519.